//package com.easy.frame.message;
//
//import com.alibaba.fastjson.JSONObject;
//import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
//import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
//import com.easy.frame.base.basic.ServiceResponse;
//import com.easy.frame.base.basic.enums.ResponseCodeEnum;
//import com.easy.frame.base.basic.exception.ServiceException;
//import com.easy.frame.base.basic.util.DateUtils;
//import com.easy.frame.common.redis.RedisUtil;
//import com.easy.frame.message.constance.RabbitMqCommon;
//import com.easy.frame.message.constance.RedisCommon;
//import com.easy.frame.message.entity.NewsMsgTemplate;
//import com.easy.frame.message.entity.SendTemplateDto;
//import com.easy.frame.message.entity.StaffReceive;
//import com.easy.frame.message.msg.IMessage;
//import com.easy.frame.message.send.EMSSend;
//import com.easy.frame.message.send.EmailSend;
//import com.easy.frame.servers.sys.entity.NewTiming;
//import com.easy.frame.servers.sys.entity.SysStaff;
//import com.easy.frame.servers.sys.service.NewTimingService;
//import com.easy.frame.servers.sys.service.staff.SysStaffService;
//import org.springframework.amqp.rabbit.connection.CorrelationData;
//import org.springframework.amqp.rabbit.core.RabbitTemplate;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.stereotype.Component;
//import org.springframework.util.StringUtils;
//
//import java.text.MessageFormat;
//import java.text.ParseException;
//import java.text.SimpleDateFormat;
//import java.util.*;
//import java.util.stream.Collectors;
//
///**
// * 用来统一模板发送，发送的内容必须要从模板中获取，否则则看作为非正常途径获取（用来规范发送内容）
// * 1.前端根据类型选择对应的消息模板（所有的模板内容都储存在redis中）
// * 包含模板id、定时发送时间、发送内容、接收人集合、
// * 1> 校验前端参数正确性
// * 2> 查询redis中的模板信息
// * 3>
// *
// * @author tp
// */
//@Component
//public class TemplateSend {
//
//    @Autowired
//    private RabbitTemplate rabbitTemplate;
//
//    @Autowired
//    NewTimingService newTimingService;
//
//    @Autowired
//    SysStaffService sysStaffService;
//
//    /**
//     * (消息中心暂未将发送的消息体进行入库保存)
//     * redis的模板消息储存方式（key+模板id，key+模板id，消息字符串）
//     * 1.校验模板信息；
//     * 2.根据模板id选择对应的模板消息体（所有的模板一开始就按照固定的前缀存入redis库中）
//     * 3.如果有该模板消息：
//     * 1> 查询出所有的模板消息；
//     * 2> 获取对应的模板消息体信息（前缀key+模板id，键值key+模板id）；
//     * 3> 校验格式（消息体符合规则）；
//     * 4> 如果包含定时时间，就延迟发送消息体：
//     * 1> 保存消息内容并入库；
//     * 2> 延迟发送至mq等待被消费处理；
//     * 5> 包装好消息进行批量发送
//     */
//    public ServiceResponse<?> send(SendTemplateDto<StaffReceive> sendTemplateDto) {
//        NewsMsgTemplate template;
//        //校验前端传入模板的正确性
//        checkReceiveType(sendTemplateDto);
//        //根据id查询模板信息
//        boolean hasTemplate = RedisUtil.getInstance().hashKey(RedisCommon.NEWS_TEMP_PRE, RedisCommon.TEMP_PRE + sendTemplateDto.getTemplateId());
//        if (hasTemplate) {
//            //获取redis中的模板内容
//            String templateString = (String) RedisUtil.getInstance().
//                    hGetField(RedisCommon.NEWS_TEMP_PRE, RedisCommon.TEMP_PRE + sendTemplateDto.getTemplateId());
//
//            //补充：String jsonStr = JSONObject.toJSONString(entity);  使用这种方式进行对象保存在redis中（互转）
//            template = JSONObject.parseObject(templateString, NewsMsgTemplate.class);
//            //校验消息内容的格式（根据长度）
//            if (StringUtils.isEmpty(template)) {
//                throw new ServiceException("库中没有对应的消息模板体，请联系管理员添加");
//            }
//            //校验模板内容格式
//            checkMessageFormat(template, sendTemplateDto.getContent());
//            String channelCode = template.getChannelCode();
//            //如果包含延迟发送的时间，那么就发送至队列中等待消费
//            if (!StringUtils.isEmpty(sendTemplateDto.getSendTime())) {
//                //获取消息变量
//                String[] formatMes = sendTemplateDto.getContent().split(",");
//                String format = ServiceException.parseInfo(template.getContent(), (Object) formatMes);
//                //保存数据
//                NewTiming newTiming = handlerTimerSave(sendTemplateDto, format);
//                //消息延迟发送(消息模板id做唯一标识)
//                handlerTimerSend(sendTemplateDto, newTiming.getTempId());
//                return new ServiceResponse<>(ResponseCodeEnum.SUCCESS);
//            }
//            List<StaffReceive> users;
//            //如果是发送给设定的接收人的逻辑
//            if (0 == sendTemplateDto.getSendType()) {
//                users = receiveUsers(sendTemplateDto.getSystemUser());
//            } else {
//                users = sendTemplateDto.getReceiveUser();
//            }
//            //批量发送
//            matchingSend(sendTemplateDto, users, channelCode);
//
//        }
//        return new ServiceResponse<>(ResponseCodeEnum.SUCCESS);
//    }
//
//    /**
//     * 消息内容入库，任务消息入数据库，接收人入redis库
//     *
//     * @param dto     消息体
//     * @param content 内容
//     */
//    public NewTiming handlerTimerSave(SendTemplateDto<StaffReceive> dto, String content) {
//        List<StaffReceive> users;
//        if (0 == dto.getSendType()) {
//            //receiveUser没有值则使用模板接收人群
//            users = receiveUsers(dto.getSystemUser());
//            if (ObjectUtils.isEmpty(users)) {
//                throw new ServiceException("无效的接收目标");
//            }
//        }
//        users = dto.getReceiveUser();
//        //将该接收人数据存入redis中（因为这块数据是临时的，没必要入库搞的那么麻烦，消费了之后就删的）
//        users.forEach(s -> {
//            Map<String, String> map = new HashMap<>(10);
//            map.put("username", s.getUsername());
//            map.put("phone", s.getPhone());
//            map.put("name", s.getName());
//            map.put("tenantId", String.valueOf(s.getTenantId()));
//            RedisUtil.getInstance().add(String.valueOf(s.getId()), map);
//        });
//
//        //定时任务入库（这部分只存入接收人的idList做为关联条件）
//        NewTiming timing = new NewTiming();
//        timing.setContent(content);
//        timing.setSendTime(DateUtils.strToDate(dto.getSendTime()));
//        timing.setSecond((int) DateUtils.dateSubtraction(DateUtils.getSystemTime(), dto.getSendTime()));
//        timing.setIsSend(0);
//        timing.setTempId(dto.getTemplateId());
//        if (dto.getSendType() == 0) {
//            timing.setReceiveUser(dto.getSystemUser().stream().map(String::valueOf).collect(Collectors.joining(",")));
//        } else {
//            List<Long> userList = dto.getReceiveUser().stream().map(StaffReceive::getId).collect(Collectors.toList());
//            timing.setReceiveUser(userList.stream().map(String::valueOf).collect(Collectors.joining(",")));
//        }
//        newTimingService.save(timing);
//        return timing;
//    }
//
//    /**
//     * 批量发送
//     *
//     * @param sendTemplateDto 消息体内容
//     * @param users           接收人
//     * @param channelCode     发送渠道（比如：ems、email。。。。）
//     */
//    public void matchingSend(SendTemplateDto<StaffReceive> sendTemplateDto, List<StaffReceive> users, String channelCode) {
//        MessageFactory factory = new MessageFactory();
//        IMessage emsSend = factory.create(null);
//        if (channelCode.equals(SendClientEnum.MSG.code)) {
//            emsSend = factory.create(EMSSend.class);
//        }
//        if (channelCode.equals(SendClientEnum.APP.code)) {
//            emsSend = factory.create(EMSSend.class);
//        }
//        if (channelCode.equals(SendClientEnum.EMAIL.code)) {
//            emsSend = factory.create(EmailSend.class);
//        }
//        if (channelCode.equals(SendClientEnum.WEB.code)) {
//            emsSend = factory.create(EmailSend.class);
//        }
//        emsSend.send(sendTemplateDto, users);
//    }
//
//
//    /**
//     * 1.校验接收人信息；
//     * 2.校验接收定时时间；
//     */
//    public void checkReceiveType(SendTemplateDto<StaffReceive> dto) {
//        if (1 == dto.getSendType()) {
//            if (ObjectUtils.isEmpty(dto.getReceiveUser())) {
//                throw new ServiceException("消息接收者不能为空");
//            }
//        }
//        if (!StringUtils.isEmpty(dto.getSendTime())) {
//            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//            try {
//                Date date = format.parse(dto.getSendTime());
//                if (date.before(new Date())) {
//                    throw new ServiceException("消息发送失败，且发送时间必须大于当前时间");
//                }
//            } catch (ParseException e) {
//                throw new ServiceException("消息发送失败，无效的发送时间。正确的格式为：yyyy-MM-dd HH:mm:ss");
//            }
//        }
//    }
//
//    /**
//     * 检测发送的模板内容格式
//     *
//     * @param template    redis中的模板内容
//     * @param sendContent 前端传入的模板内容
//     */
//    private void checkMessageFormat(NewsMsgTemplate template, String sendContent) {
//        //判断模板里面的内容是否存在替换内容，且判断传入的内容是否和模板里面的内容长度是否一致
//        MessageFormat temp = new MessageFormat(template.getContent());
//        int count = temp.getFormats().length;
//        //不等于零表示存在需要替换的内容，length的大小表示需要替换的内容有多少个
//        if (count != 0) {
//            //传入的内容长度和模板的需要替换的内容长度做对比，不一致表示传入的参有误
//            if (com.baomidou.mybatisplus.core.toolkit.StringUtils.isBlank(sendContent)) {
//                throw new ServiceException("消息发送失败，缺少必要的模板内容参数。" +
//                        "模板内容：【" + template.getContent() + "】" + "传入的参数数据:【" + sendContent + "】");
//            }
//            String[] split = sendContent.split(",");
//            int length = split.length;
//            if (count != length) {
//                throw new ServiceException("消息发送失败，缺少必要的模板内容参数。" +
//                        "模板内容：【" + template.getContent() + "】" + "传入的参数数据:【" + sendContent + "】");
//            }
//        }
//    }
//
//    /**
//     * 该发送方式只发送任务消息id，接受者接受到直接消费即可
//     */
//    public void handlerTimerSend(SendTemplateDto<StaffReceive> sendTemplateDto, Long correlationId) {
//        int delay = 0;
//        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        try {
//            Date date = format.parse(sendTemplateDto.getSendTime());
//            delay = (int) DateUtils.dateTogether(new Date(), date);
//        } catch (ParseException e) {
//            e.printStackTrace();
//        }
//        CorrelationData correlationData = new CorrelationData();
//        //发送信息添加唯一标识。
//        correlationData.setId(RabbitMqCommon.DELAYED_CORRELATION_ID_PRE + correlationId);
//        int finalDelay = delay;
//        rabbitTemplate.convertAndSend(RabbitMqCommon.DELAYED_EXCHANGE_NAME,
//                RabbitMqCommon.DELAYED_ROUTING_KEY, RabbitMqCommon.DELAYED_CORRELATION_ID_PRE + correlationId, (message) -> {
//                    //设置消息的过期时间毫秒
//                    message.getMessageProperties().setDelay(finalDelay * 1000);
//                    message.getMessageProperties().setCorrelationId(RabbitMqCommon.DELAYED_CORRELATION_ID_PRE + correlationId);
//                    return message;
//
//                }, correlationData);
//    }
//
//    /**
//     * 消息模板发送时所接收人群的处理
//     *
//     * @param systemUser 接收人群
//     * @return 返回模板人群信息
//     */
//    private List<StaffReceive> receiveUsers(List<Integer> systemUser) {
//        List<StaffReceive> receiveList = new ArrayList<>();
//        List<SysStaff> systemList = sysStaffService.list(new LambdaQueryWrapper<SysStaff>()
//                .in(SysStaff::getId, systemUser));
//        systemList.forEach(s -> {
//            StaffReceive staffReceive = new StaffReceive();
//            staffReceive.setTenantId(s.getTenantId());
//            staffReceive.setUsername(s.getUsername());
//            staffReceive.setPhone(s.getPhone());
//            staffReceive.setId(s.getId());
//            staffReceive.setTenantId(s.getTenantId());
//            receiveList.add(staffReceive);
//        });
//        return receiveList;
//    }
//
//}
